{
 "cells": [
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "# 模型构造\n",
    "##"
   ],
   "id": "4d3c465409214e09"
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "首先定义一个单层感知机网络结构",
   "id": "69c9048af882739a"
  },
  {
   "metadata": {
    "collapsed": true,
    "ExecuteTime": {
     "end_time": "2025-08-16T11:51:53.394713Z",
     "start_time": "2025-08-16T11:51:49.191625Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import torch\n",
    "from torch import nn\n",
    "from torch.nn import functional as f"
   ],
   "id": "5e8328f3cdc40bf",
   "outputs": [],
   "execution_count": 1
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-16T11:54:43.316217Z",
     "start_time": "2025-08-16T11:54:43.312793Z"
    }
   },
   "cell_type": "code",
   "source": [
    "net = nn.Sequential(\n",
    "    nn.Linear(4,8),\n",
    "    nn.ReLU(),\n",
    "    nn.Linear(8,1)\n",
    ")\n",
    "X = torch.randn(size=(2,4))\n",
    "print(net(X))"
   ],
   "id": "2e88833546c06460",
   "outputs": [],
   "execution_count": 2
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "### 参数访问",
   "id": "3297d4216fd098c2"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-15T13:36:09.211174Z",
     "start_time": "2025-08-15T13:36:09.207173Z"
    }
   },
   "cell_type": "code",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "OrderedDict({'weight': tensor([[-0.2288, -0.2350,  0.4129,  0.2738],\n",
      "        [-0.1064, -0.0829, -0.2900, -0.4329],\n",
      "        [-0.1114, -0.2136,  0.3047,  0.0042],\n",
      "        [-0.1385,  0.4450,  0.0029, -0.3234],\n",
      "        [-0.3729,  0.4073,  0.4312,  0.2075],\n",
      "        [-0.0345,  0.3692, -0.4639,  0.1282],\n",
      "        [-0.1311,  0.1488, -0.1141, -0.2032],\n",
      "        [ 0.3773, -0.2258, -0.2866,  0.2621]]), 'bias': tensor([-0.3736, -0.2815,  0.4353, -0.2388, -0.4542,  0.0367, -0.1988, -0.2326])})\n",
      "OrderedDict({'weight': tensor([[-0.2118, -0.1667, -0.0333, -0.0475,  0.3181,  0.1872,  0.2779,  0.2137]]), 'bias': tensor([-0.3064])})\n"
     ]
    }
   ],
   "execution_count": 8,
   "source": [
    "print(net[0].state_dict())\n",
    "print(net[2].state_dict())\n",
    "## net.state_dict用于获取网络参数，如权重和偏置"
   ],
   "id": "133f9a7ef96bcff7"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-15T13:36:26.713134Z",
     "start_time": "2025-08-15T13:36:26.708130Z"
    }
   },
   "cell_type": "code",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "OrderedDict({'0.weight': tensor([[-0.2288, -0.2350,  0.4129,  0.2738],\n",
      "        [-0.1064, -0.0829, -0.2900, -0.4329],\n",
      "        [-0.1114, -0.2136,  0.3047,  0.0042],\n",
      "        [-0.1385,  0.4450,  0.0029, -0.3234],\n",
      "        [-0.3729,  0.4073,  0.4312,  0.2075],\n",
      "        [-0.0345,  0.3692, -0.4639,  0.1282],\n",
      "        [-0.1311,  0.1488, -0.1141, -0.2032],\n",
      "        [ 0.3773, -0.2258, -0.2866,  0.2621]]), '0.bias': tensor([-0.3736, -0.2815,  0.4353, -0.2388, -0.4542,  0.0367, -0.1988, -0.2326]), '2.weight': tensor([[-0.2118, -0.1667, -0.0333, -0.0475,  0.3181,  0.1872,  0.2779,  0.2137]]), '2.bias': tensor([-0.3064])})\n"
     ]
    }
   ],
   "execution_count": 9,
   "source": "print(net.state_dict()) ##也可以输出所有层的参数",
   "id": "d8d0010e32728066"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-15T13:38:15.140386Z",
     "start_time": "2025-08-15T13:38:15.135759Z"
    }
   },
   "cell_type": "code",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Parameter containing:\n",
      "tensor([-0.3736, -0.2815,  0.4353, -0.2388, -0.4542,  0.0367, -0.1988, -0.2326],\n",
      "       requires_grad=True)\n",
      "Parameter containing:\n",
      "tensor([[-0.2288, -0.2350,  0.4129,  0.2738],\n",
      "        [-0.1064, -0.0829, -0.2900, -0.4329],\n",
      "        [-0.1114, -0.2136,  0.3047,  0.0042],\n",
      "        [-0.1385,  0.4450,  0.0029, -0.3234],\n",
      "        [-0.3729,  0.4073,  0.4312,  0.2075],\n",
      "        [-0.0345,  0.3692, -0.4639,  0.1282],\n",
      "        [-0.1311,  0.1488, -0.1141, -0.2032],\n",
      "        [ 0.3773, -0.2258, -0.2866,  0.2621]], requires_grad=True)\n"
     ]
    }
   ],
   "execution_count": 11,
   "source": [
    "print(net[0].bias) # 可以直接获取指定项设置\n",
    "print(net[0].weight)"
   ],
   "id": "16f29d8be1034d73"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-15T13:39:10.858653Z",
     "start_time": "2025-08-15T13:39:10.855034Z"
    }
   },
   "cell_type": "code",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([-0.3736, -0.2815,  0.4353, -0.2388, -0.4542,  0.0367, -0.1988, -0.2326])\n",
      "None\n"
     ]
    }
   ],
   "execution_count": 14,
   "source": [
    "print(net[0].bias.data)\n",
    "print(net[0].bias.grad) ## 可以访问具体的参数数值以及梯度"
   ],
   "id": "846b132fc2265451"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-15T13:41:57.774339Z",
     "start_time": "2025-08-15T13:41:57.770830Z"
    }
   },
   "cell_type": "code",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[-0.2288, -0.2350,  0.4129,  0.2738],\n",
      "        [-0.1064, -0.0829, -0.2900, -0.4329],\n",
      "        [-0.1114, -0.2136,  0.3047,  0.0042],\n",
      "        [-0.1385,  0.4450,  0.0029, -0.3234],\n",
      "        [-0.3729,  0.4073,  0.4312,  0.2075],\n",
      "        [-0.0345,  0.3692, -0.4639,  0.1282],\n",
      "        [-0.1311,  0.1488, -0.1141, -0.2032],\n",
      "        [ 0.3773, -0.2258, -0.2866,  0.2621]])\n"
     ]
    }
   ],
   "execution_count": 18,
   "source": "print(net.state_dict()['0.weight'].data)##也可以直接指定字典key访问参数",
   "id": "a85ad260df284ff2"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-16T11:54:46.260119Z",
     "start_time": "2025-08-16T11:54:46.185883Z"
    }
   },
   "cell_type": "code",
   "source": "",
   "id": "b47b3dacad770645",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([-2., -1.,  0.,  1.,  2.])"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 3
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-15T13:41:18.366106Z",
     "start_time": "2025-08-15T13:41:18.362778Z"
    }
   },
   "cell_type": "code",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "('0.weight', torch.Size([8, 4])) ('0.bias', torch.Size([8])) ('2.weight', torch.Size([1, 8])) ('2.bias', torch.Size([1]))\n"
     ]
    }
   ],
   "execution_count": 17,
   "source": "print(*[(name,param.shape) for name , param in net.named_parameters()]) ##由于参数以字典形式存储，可以方便的使用列表推导式获取权重信息",
   "id": "48a0a1b2a05213dd"
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "### 访问嵌套块参数",
   "id": "abea04ba16854068"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-15T13:49:40.051053Z",
     "start_time": "2025-08-15T13:49:40.047547Z"
    }
   },
   "cell_type": "code",
   "source": [
    "def basic_block():\n",
    "    '''定义基础块结构'''\n",
    "    return nn.Sequential(nn.Linear(4, 8), nn.ReLU(), nn.Linear(8, 4), nn.ReLU())\n",
    "\n",
    "\n",
    "def nested_block():\n",
    "    '''生成嵌套块'''\n",
    "    net = nn.Sequential()\n",
    "    for i in range(4):\n",
    "        net.add_module(name=f'block {i}', module=basic_block())\n",
    "    return net"
   ],
   "id": "bdef49fc258adf11",
   "outputs": [],
   "execution_count": 25
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-15T13:51:31.804999Z",
     "start_time": "2025-08-15T13:51:31.799419Z"
    }
   },
   "cell_type": "code",
   "source": [
    "rgnet = nn.Sequential(nested_block(),nn.Linear(4,1))\n",
    "print(rgnet(X))"
   ],
   "id": "3b1cf755e1e7fcc",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[-0.1453],\n",
      "        [-0.1455]], grad_fn=<AddmmBackward0>)\n"
     ]
    }
   ],
   "execution_count": 27
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-15T13:51:51.408541Z",
     "start_time": "2025-08-15T13:51:51.405711Z"
    }
   },
   "cell_type": "code",
   "source": "print(rgnet) ## 输出模型结构",
   "id": "302cd018c76ddf21",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Sequential(\n",
      "  (0): Sequential(\n",
      "    (block 0): Sequential(\n",
      "      (0): Linear(in_features=4, out_features=8, bias=True)\n",
      "      (1): ReLU()\n",
      "      (2): Linear(in_features=8, out_features=4, bias=True)\n",
      "      (3): ReLU()\n",
      "    )\n",
      "    (block 1): Sequential(\n",
      "      (0): Linear(in_features=4, out_features=8, bias=True)\n",
      "      (1): ReLU()\n",
      "      (2): Linear(in_features=8, out_features=4, bias=True)\n",
      "      (3): ReLU()\n",
      "    )\n",
      "    (block 2): Sequential(\n",
      "      (0): Linear(in_features=4, out_features=8, bias=True)\n",
      "      (1): ReLU()\n",
      "      (2): Linear(in_features=8, out_features=4, bias=True)\n",
      "      (3): ReLU()\n",
      "    )\n",
      "    (block 3): Sequential(\n",
      "      (0): Linear(in_features=4, out_features=8, bias=True)\n",
      "      (1): ReLU()\n",
      "      (2): Linear(in_features=8, out_features=4, bias=True)\n",
      "      (3): ReLU()\n",
      "    )\n",
      "  )\n",
      "  (1): Linear(in_features=4, out_features=1, bias=True)\n",
      ")\n"
     ]
    }
   ],
   "execution_count": 28
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "### 参数初始化",
   "id": "b3f1f3b002c3b232"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-15T13:56:38.340999Z",
     "start_time": "2025-08-15T13:56:38.337997Z"
    }
   },
   "cell_type": "code",
   "source": [
    "def init_normal(net):\n",
    "    if type(net) == nn.Linear:\n",
    "        nn.init.normal_(net.weight, mean=0, std=0.01)\n",
    "        nn.init.zeros_(net.bias)\n",
    "def init_xavier(net):\n",
    "    if type(net) == nn.Linear:\n",
    "        nn.init.xavier_uniform_(net.weight)"
   ],
   "id": "4842d5c10cf6fc77",
   "outputs": [],
   "execution_count": 30
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-15T13:56:39.648120Z",
     "start_time": "2025-08-15T13:56:39.644121Z"
    }
   },
   "cell_type": "code",
   "source": "net.apply(init_normal) ##使用apply方法对每一层应用初始化函数，类似于map",
   "id": "11bfe27b093fcf91",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Sequential(\n",
       "  (0): Linear(in_features=4, out_features=8, bias=True)\n",
       "  (1): ReLU()\n",
       "  (2): Linear(in_features=8, out_features=1, bias=True)\n",
       ")"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 31
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-15T13:56:41.048802Z",
     "start_time": "2025-08-15T13:56:41.045751Z"
    }
   },
   "cell_type": "code",
   "source": "print(net.state_dict())",
   "id": "d4b2b3a7b0cb7f32",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "OrderedDict({'0.weight': tensor([[ 1.6833e-02,  8.2850e-03, -2.5789e-02,  8.7199e-03],\n",
      "        [-1.3158e-02,  7.7308e-03, -2.6955e-03,  1.7461e-03],\n",
      "        [ 4.5982e-03,  1.2928e-03, -2.4825e-03, -7.9476e-03],\n",
      "        [-1.1699e-02,  6.7593e-03, -1.8553e-02,  4.2155e-03],\n",
      "        [ 1.2020e-02, -9.4872e-03, -4.7427e-03,  3.3482e-03],\n",
      "        [ 7.7605e-03,  2.1205e-05,  1.7821e-02, -1.0400e-03],\n",
      "        [ 2.2918e-04, -1.1274e-02, -1.2129e-02,  5.5372e-03],\n",
      "        [-6.8066e-03,  9.9214e-03, -3.1982e-03,  1.4128e-02]]), '0.bias': tensor([0., 0., 0., 0., 0., 0., 0., 0.]), '2.weight': tensor([[ 0.0070, -0.0049, -0.0018,  0.0045,  0.0085,  0.0077, -0.0065, -0.0058]]), '2.bias': tensor([0.])})\n"
     ]
    }
   ],
   "execution_count": 32
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-15T13:57:43.810807Z",
     "start_time": "2025-08-15T13:57:43.807386Z"
    }
   },
   "cell_type": "code",
   "source": [
    "## 也可以通过索引指定某一层应用特定初始化函数\n",
    "net[2].apply(init_xavier)\n",
    "print(net[2].weight.data)"
   ],
   "id": "6544ec502efe4e7d",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[-0.5843,  0.4665,  0.1092, -0.6607,  0.3574, -0.3809,  0.4221,  0.1288]])\n"
     ]
    }
   ],
   "execution_count": 33
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "### 定义共享层（参数绑定）\n",
    "在torch中将层赋值给变量后，只要是使用该变量创建的层，参数都是一致的"
   ],
   "id": "3ebb8df6a1ec8fe3"
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "",
   "id": "6e0e7ebce593fa35"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-15T14:00:00.556842Z",
     "start_time": "2025-08-15T14:00:00.553730Z"
    }
   },
   "cell_type": "code",
   "source": "shared = nn.Linear(8,8)",
   "id": "6eef21cc807bc5cc",
   "outputs": [],
   "execution_count": 34
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-15T14:00:03.168518Z",
     "start_time": "2025-08-15T14:00:03.164400Z"
    }
   },
   "cell_type": "code",
   "source": [
    "net = nn.Sequential(nn.Linear(4, 8), nn.ReLU(),\n",
    "                    shared, nn.ReLU(),\n",
    "                    shared, nn.ReLU(),\n",
    "                    nn.Linear(8, 1))\n",
    "net(X)\n",
    "# 检查参数是否相同\n",
    "print(net[2].weight.data[0] == net[4].weight.data[0])\n",
    "net[2].weight.data[0, 0] = 100\n",
    "# 确保它们实际上是同一个对象，而不只是有相同的值\n",
    "print(net[2].weight.data[0] == net[4].weight.data[0])"
   ],
   "id": "55074b6ac685513d",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([True, True, True, True, True, True, True, True])\n",
      "tensor([True, True, True, True, True, True, True, True])\n"
     ]
    }
   ],
   "execution_count": 36
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
